package com.suning.sawp.service.impl.oga.bi;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.suning.framework.dal.client.DalClient;
import com.suning.sawp.dto.oga.bi.DateDevelopSaleDetail;
import com.suning.sawp.dto.oga.bi.DevelopSaleDetail;
import com.suning.sawp.dto.oga.bi.DevelopSaleDetailWithUpdateTime;
import com.suning.sawp.dto.oga.bi.SimpleRange;
import com.suning.sawp.dto.oga.bi.StaffDevelopInfoWithSale;
import com.suning.sawp.dto.oga.bi.StaffDevelopSaleDetail;
import com.suning.sawp.dto.oga.bi.StaffDevelopSaleDetailWithUpdateTime;
import com.suning.sawp.po.bi.BIStaffDevelopSale;
import com.suning.sawp.po.bi.BiDateDevelopSale;
import com.suning.sawp.po.bi.BiDevelopSale;
import com.suning.sawp.po.bi.BiStaffArriveSaleDayEntity;
import com.suning.sawp.po.bi.BiStaffDevelopWithSale;
import com.suning.sawp.service.impl.oga.bi.support.Callback;
import com.suning.sawp.service.impl.oga.bi.support.Populates;

/**
 * 拓展销售统计
 * 
 * @author 13071602
 *
 */
public abstract class BIDevelopSaleService {

    @Autowired
    protected DalClient dalClient;

 

    /**
     * 销售额排行榜
     * 
     * @return
     */
    public List<StaffDevelopInfoWithSale> queryStaffDevelopSaleLeaderBoardInfo(String storeCode, int top,
            int timeOffset) {
        List<? extends BiStaffDevelopWithSale> staffSales = queryStaffDevelopSaleLeaderBoard(storeCode, top,
                timeOffset);

        return Lists.transform(staffSales, new Function<BiStaffDevelopWithSale, StaffDevelopInfoWithSale>() {
            @Override
            public StaffDevelopInfoWithSale apply(BiStaffDevelopWithSale sale) {
                StaffDevelopInfoWithSale info = new StaffDevelopInfoWithSale();
                Populates.populateDevelopInfo(info, sale);
                Populates.populateStaffInfo(info, sale);
                Populates.populateSaleAmount(info, sale);
                return info;
            }
        });
    }

    protected abstract List<? extends BiStaffDevelopWithSale> queryStaffDevelopSaleLeaderBoard(String storeCode,
            int top, int timeOffset);

    /**
     * 门店外拓销售转化汇总
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    public DevelopSaleDetailWithUpdateTime queryStoreDevelopingSaleInfo(String storeCode, int offset) {
        final DevelopSaleDetailWithUpdateTime developSaleDetail = new DevelopSaleDetailWithUpdateTime();
        BiDevelopSale sale = queryStoreDevelopingSale(storeCode, offset, new Callback<String>() {
            @Override
            public void withValue(String range) {
                developSaleDetail.setTimeRange(range);
            }
        });
        if (null == sale) {
            throw new IllegalStateException("无销售数据");
        }
        populateDevelopSaleDetail(developSaleDetail, sale);
        return developSaleDetail;
    }

    /**
     * 门店到店销售转化汇总
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    public DevelopSaleDetailWithUpdateTime queryStoreArriveSaleInfo(String storeCode, int offset) {
        final DevelopSaleDetailWithUpdateTime developSaleDetail = new DevelopSaleDetailWithUpdateTime();
        BiDevelopSale sale = queryStoreArriveSale(storeCode, offset, new Callback<String>() {
            @Override
            public void withValue(String range) {
                developSaleDetail.setTimeRange(range);
            }
        });
        if (null == sale) {
            throw new IllegalStateException("无销售数据");
        }
        populateDevelopSaleDetail(developSaleDetail, sale);
        return developSaleDetail;
    }

    /**
     * 门店熟人推荐销售转化汇总
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    public DevelopSaleDetailWithUpdateTime queryStoreRecommendSaleInfo(String storeCode, int offset) {

        final DevelopSaleDetailWithUpdateTime developSaleDetail = new DevelopSaleDetailWithUpdateTime();
        BiDevelopSale sale = queryStoreRecommendSale(storeCode, offset, new Callback<String>() {
            @Override
            public void withValue(String range) {
                developSaleDetail.setTimeRange(range);
            }
        });
        if (null == sale) {
            throw new IllegalStateException("无销售数据");
        }

        populateDevelopSaleDetail(developSaleDetail, sale);
        return developSaleDetail;
    }

    public StaffDevelopSaleDetailWithUpdateTime queryStaffDevelopingSaleInfo(String storeCode, String staffId,
            int offset) {
        final StaffDevelopSaleDetailWithUpdateTime developSaleDetail = new StaffDevelopSaleDetailWithUpdateTime();
        BIStaffDevelopSale sale = queryStaffDevelopingSale(storeCode, staffId, offset, new Callback<String>() {
            @Override
            public void withValue(String range) {
                developSaleDetail.setTimeRange(range);
            }
        });
        if (null == sale) {
            throw new IllegalStateException("无销售数据");
        }

        populateDevelopSaleDetail(developSaleDetail, sale);
        Populates.populateStaffInfo(developSaleDetail, sale);
        return developSaleDetail;
    }

    public StaffDevelopSaleDetailWithUpdateTime queryStaffArriveSaleInfo(String storeCode, String staffId, int offset) {

        final StaffDevelopSaleDetailWithUpdateTime developSaleDetail = new StaffDevelopSaleDetailWithUpdateTime();
        BIStaffDevelopSale sale = queryStaffArriveSale(storeCode, staffId, offset, new Callback<String>() {
            @Override
            public void withValue(String range) {
                developSaleDetail.setTimeRange(range);
            }
        });
        if (null == sale) {
            throw new IllegalStateException("无销售数据");
        }

        populateDevelopSaleDetail(developSaleDetail, sale);
        Populates.populateStaffInfo(developSaleDetail, sale);
        return developSaleDetail;
    }

    public StaffDevelopSaleDetailWithUpdateTime queryStaffRecommendSaleInfo(String storeCode, String staffId,
            int offset) {
        final StaffDevelopSaleDetailWithUpdateTime developSaleDetail = new StaffDevelopSaleDetailWithUpdateTime();
        BIStaffDevelopSale sale = queryStaffRecommendSale(storeCode, staffId, offset, new Callback<String>() {
            @Override
            public void withValue(String range) {
                developSaleDetail.setTimeRange(range);
            }
        });
        if (null == sale) {
            throw new IllegalStateException("无销售数据");
        }

        populateDevelopSaleDetail(developSaleDetail, sale);
        Populates.populateStaffInfo(developSaleDetail, sale);
        return developSaleDetail;
    }

    /**
     * 单个店员外拓销售转化
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    public List<DateDevelopSaleDetail> queryStaffDevelopingSaleInfos(String storeCode, String staffId, int offset) {
        SimpleRange<String> range = getStaffSaleRange(offset);
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("startDate", range.getLowerBound());
        paramMap.put("endDate", range.getUpperBound());
        paramMap.put("storeCode", storeCode);
        List<? extends BiDateDevelopSale> sales = dalClient.queryForList(
                "BIDevelopSaleService.queryStaffDevelopingSale", paramMap, BiStaffArriveSaleDayEntity.class);
        return Lists.transform(sales, new Function<BiDateDevelopSale, DateDevelopSaleDetail>() {
            @Override
            public DateDevelopSaleDetail apply(BiDateDevelopSale sale) {
                DateDevelopSaleDetail developSaleDetail = new DateDevelopSaleDetail();
                populateDevelopSaleDetail(developSaleDetail, sale);
                Populates.populateDate(developSaleDetail, sale);
                return developSaleDetail;
            }
        });
    }

    /**
     * 单个店员到店销售转化汇总
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    public List<DateDevelopSaleDetail> queryStaffArriveSaleInfos(String storeCode, String staffId, int offset) {
        SimpleRange<String> range = getStaffSaleRange(offset);
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("startDate", range.getLowerBound());
        paramMap.put("endDate", range.getUpperBound());
        paramMap.put("storeCode", storeCode);
        paramMap.put("staffId", staffId);
        List<? extends BiDateDevelopSale> sales = dalClient.queryForList("BIDevelopSaleService.queryStaffArriveSale",
                paramMap, BiStaffArriveSaleDayEntity.class);
        return Lists.transform(sales, new Function<BiDateDevelopSale, DateDevelopSaleDetail>() {
            @Override
            public DateDevelopSaleDetail apply(BiDateDevelopSale sale) {
                DateDevelopSaleDetail developSaleDetail = new DateDevelopSaleDetail();
                populateDevelopSaleDetail(developSaleDetail, sale);
                Populates.populateDate(developSaleDetail, sale);
                return developSaleDetail;
            }
        });
    }

    /**
     * 单个店员熟人推荐销售转化汇总
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    public List<DateDevelopSaleDetail> queryStaffRecommendSaleInfos(String storeCode, String staffId, int offset) {
        SimpleRange<String> range = getStaffSaleRange(offset);
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("startDate", range.getLowerBound());
        paramMap.put("endDate", range.getUpperBound());
        paramMap.put("storeCode", storeCode);
        paramMap.put("staffId", staffId);
        List<? extends BiDateDevelopSale> sales = dalClient.queryForList("BIDevelopSaleService.queryStaffRecommendSale",
                paramMap, BiStaffArriveSaleDayEntity.class);
        return Lists.transform(sales, new Function<BiDateDevelopSale, DateDevelopSaleDetail>() {
            @Override
            public DateDevelopSaleDetail apply(BiDateDevelopSale sale) {
                DateDevelopSaleDetail developSaleDetail = new DateDevelopSaleDetail();
                populateDevelopSaleDetail(developSaleDetail, sale);
                Populates.populateDate(developSaleDetail, sale);
                return developSaleDetail;
            }
        });
    }

    /**
     * 所有店员外拓销售转化
     * 
     * @param storeCode
     * @param offset
     * @param cateCode null代表未关联品类人员
     * @return
     */
    public List<StaffDevelopSaleDetail> queryStaffsDevelopingSaleInfo(String storeCode, String cateCode, int offset) {
        List<? extends BIStaffDevelopSale> staffs = queryStaffsDevelopingSale(storeCode, cateCode, offset);
        return Lists.transform(staffs, new Function<BIStaffDevelopSale, StaffDevelopSaleDetail>() {
            @Override
            public StaffDevelopSaleDetail apply(BIStaffDevelopSale sale) {
                StaffDevelopSaleDetail developSaleDetail = new StaffDevelopSaleDetail();
                populateDevelopSaleDetail(developSaleDetail, sale);
                Populates.populateStaffInfo(developSaleDetail, sale);
                return developSaleDetail;
            }
        });
    }

    /**
     * 所有店员到店销售转化汇总
     * 
     * @param storeCode
     * @param offset
     * @param cateCode null代表未关联品类人员
     * @return
     */
    public List<StaffDevelopSaleDetail> queryStaffsArriveSaleInfo(String storeCode, String cateCode, int offset) {
        List<? extends BIStaffDevelopSale> staffs = queryStaffsArriveSale(storeCode, cateCode, offset);
        return Lists.transform(staffs, new Function<BIStaffDevelopSale, StaffDevelopSaleDetail>() {
            @Override
            public StaffDevelopSaleDetail apply(BIStaffDevelopSale sale) {
                StaffDevelopSaleDetail developSaleDetail = new StaffDevelopSaleDetail();
                populateDevelopSaleDetail(developSaleDetail, sale);
                Populates.populateStaffInfo(developSaleDetail, sale);
                return developSaleDetail;
            }
        });
    }

    /**
     * 所有店员熟人推荐销售转化汇总
     * 
     * @param storeCode
     * @param offset
     * @param cateCode null代表未关联品类人员
     * @return
     */
    public List<StaffDevelopSaleDetail> queryStaffsRecommendSaleInfo(String storeCode, String cateCode, int offset) {
        List<? extends BIStaffDevelopSale> staffs = queryStaffsRecommendSale(storeCode, cateCode, offset);
        return Lists.transform(staffs, new Function<BIStaffDevelopSale, StaffDevelopSaleDetail>() {
            @Override
            public StaffDevelopSaleDetail apply(BIStaffDevelopSale sale) {
                StaffDevelopSaleDetail developSaleDetail = new StaffDevelopSaleDetail();
                populateDevelopSaleDetail(developSaleDetail, sale);
                Populates.populateStaffInfo(developSaleDetail, sale);
                return developSaleDetail;
            }
        });

    }

    protected abstract SimpleRange<String> getStaffSaleRange(int offset);

    protected abstract List<? extends BIStaffDevelopSale> queryStaffsDevelopingSale(String storeCode, String cateCode,
            int offset);

    /**
     * 数据库查询门店下店员销售
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    protected abstract List<? extends BIStaffDevelopSale> queryStaffsArriveSale(String storeCode, String cateCode,
            int offset);

    /**
     * 数据库查询门店下店员销售
     * 
     * @param storeCode
     * @param offset
     * @return
     */
    protected abstract List<? extends BIStaffDevelopSale> queryStaffsRecommendSale(String storeCode, String cateCode,
            int offset);

    protected abstract BiDevelopSale queryStoreDevelopingSale(String storeCode, int offset, Callback<String> span);

    protected abstract BiDevelopSale queryStoreArriveSale(String storeCode, int offset, Callback<String> span);

    protected abstract BiDevelopSale queryStoreRecommendSale(String storeCode, int offset, Callback<String> span);

    protected abstract BIStaffDevelopSale queryStaffDevelopingSale(String storeCode, String staffId, int offset,
            Callback<String> span);

    protected abstract BIStaffDevelopSale queryStaffArriveSale(String storeCode, String staffId, int offset,
            Callback<String> span);

    protected abstract BIStaffDevelopSale queryStaffRecommendSale(String storeCode, String staffId, int offset,
            Callback<String> span);

    private void populateDevelopSaleDetail(DevelopSaleDetail dest, BiDevelopSale orig) {
        dest.setDevelop(orig.getDevelopNum());
        dest.setDeveloped(orig.getDevelopedNum());
        dest.setDevelopedRate(orig.getDevelopedRate());
        dest.setDevelopedOrder(orig.getDevelopedOrder());
        dest.setSaleAmount(orig.getDevelopedSale());
    }

}
